package com.david.func_test

//import com.bytedance.sdk.open.aweme.authorize.model.Authorization
//import com.bytedance.sdk.open.douyin.DouYinOpenApiFactory
//import com.bytedance.sdk.open.douyin.DouYinOpenConfig

import android.Manifest
import android.Manifest.permission.READ_EXTERNAL_STORAGE
import android.Manifest.permission.READ_MEDIA_IMAGES
import android.Manifest.permission.READ_MEDIA_VIDEO
import android.Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED
import android.animation.Animator
import android.animation.LayoutTransition
import android.animation.ObjectAnimator
import android.animation.ValueAnimator
import android.annotation.TargetApi
import android.app.AlarmManager
import android.app.AlertDialog
import android.app.PendingIntent
import android.app.PendingIntent.FLAG_IMMUTABLE
import android.content.Context
import android.content.Intent
import android.content.res.Resources
import android.database.Cursor
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Rect
import android.graphics.RectF
import android.graphics.drawable.GradientDrawable
import android.media.MediaCodecList
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Debug
import android.os.Handler
import android.os.Looper
import android.os.Message
import android.provider.Settings
import android.text.Html
import android.util.Log
import android.util.TypedValue
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewConfiguration
import android.view.ViewGroup
import android.view.animation.Animation
import android.view.animation.AnimationUtils
import android.view.animation.BounceInterpolator
import android.view.animation.DecelerateInterpolator
import android.view.animation.TranslateAnimation
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.MediaController
import android.widget.TextView
import android.widget.Toast
import android.widget.VideoView
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.core.animation.doOnEnd
import androidx.core.view.isVisible
import androidx.core.view.marginBottom
import androidx.core.view.updateLayoutParams
import androidx.customview.widget.ViewDragHelper.STATE_IDLE
import androidx.customview.widget.ViewDragHelper.STATE_SETTLING
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.work.Constraints
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkManager
import com.airbnb.lottie.LottieAnimationView
import com.airbnb.lottie.LottieDrawable
import com.alibaba.fastjson.JSON
import com.david.core.utils.load
import com.david.core.utils.logi
import com.david.core.utils.turnWebp
import com.david.func_test.retrofitinterface.testInterface
import com.david.func_test.retrofitinterface.testInterface1
import com.david.func_test.util.AnimUtil
import com.david.func_test.util.ImFileUtil
import com.david.func_test.util.OnFileCopiedListener
import com.david.func_test.util.TestUtil
import com.david.func_test.view.AlbumCarChoosePop
import com.david.func_test.view.FloatIconView
import com.david.func_test.view.LabelBean
import com.david.func_test.view.LabelsView
import com.david.func_test.view.LimitLengthTextView
import com.david.func_test.worker.DailyWorker
import com.david.http.http.method.test.methodTestInterface
import com.david.http.http.method.test1.methodTest1Interface
import com.david.http.http.util.request
import com.david.kspmodel.TestKsp
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.luck.picture.lib.basic.PictureSelector
import com.luck.picture.lib.config.SelectMimeType
import com.luck.picture.lib.config.SelectModeConfig
import com.luck.picture.lib.entity.LocalMedia
import com.luck.picture.lib.interfaces.OnPermissionsInterceptListener
import com.luck.picture.lib.interfaces.OnRequestPermissionListener
import com.luck.picture.lib.interfaces.OnResultCallbackListener
import com.luck.picture.lib.language.LanguageConfig
import com.permissionx.guolindev.PermissionX
import com.youth.banner.util.BannerUtils.dp2px
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import io.reactivex.subjects.PublishSubject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.io.BufferedReader
import java.io.BufferedWriter
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.FileWriter
import java.io.InputStreamReader
import java.net.URL
import java.util.Calendar
import java.util.LinkedList
import java.util.concurrent.TimeUnit


//arouter：启动优化：https://blog.csdn.net/zhujiangtaotaise/article/details/112857966
@TestKsp
class MainActivity : AppCompatActivity() {
    private lateinit var btn: TextView

    //ActivityResultContracts更多用法参考里边的子类
    private val permissionLauncher =
        registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { _ ->
            // 处理权限请求结果
        }

    //图片/视频权限参考链接：https://guolin.blog.csdn.net/article/details/137410229?spm=1001.2014.3001.5502
    private fun requestPermissions() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
            permissionLauncher.launch(
                arrayOf(
                    READ_MEDIA_VIDEO,
                    READ_MEDIA_IMAGES,
                    READ_MEDIA_VISUAL_USER_SELECTED)
            )
        } else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.TIRAMISU) {
            permissionLauncher.launch(arrayOf(READ_MEDIA_IMAGES, READ_MEDIA_VIDEO))
        } else {
            permissionLauncher.launch(arrayOf(READ_EXTERNAL_STORAGE))
        }
    }


    //OpenDocument 可以申请转换为持久权限 GetContent只能临时权限
    private val openDocumentLauncher = registerForActivityResult(ActivityResultContracts.OpenDocument()) { uri ->
        // 处理返回文件的uri
        uri?.let {
            Log.e("uri", it.toString())
            Log.e("mime", contentResolver.getType(it) ?: "mime is null")// image/jpeg image/webp video/mp4 text/plain application/pdf application/vnd.openxmlformats-officedocument.wordprocessingml.document（word文档）
        }

        uri?.let {

            // 请求持久化权限
            applicationContext.contentResolver.takePersistableUriPermission(
                uri,
                Intent.FLAG_GRANT_READ_URI_PERMISSION // 或 FLAG_GRANT_WRITE_URI_PERMISSION
            )
        }
        findViewById<ImageView>(R.id.img_cloud_right).setImageURI(Uri.parse("content://com.android.providers.media.documents/document/image%3A1000350852")) //图片可以直接给iamgeView设置uri
    }

    //通过saf选择文件返回文件uri（不需要权限即可获取文件）
    private fun chooseAfsFile() {
        openDocumentLauncher.launch(arrayOf("*/*"))
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        lifecycle.addObserver(LifecycleObserverTest())

        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        findViewById<ImageView>(R.id.img_cloud_right).setImageURI(Uri.parse("content://com.android.providers.media.documents/document/image%3A1000350852")) //图片可以直接给iamgeView设置uri

        btn = findViewById(R.id.click_view)

        findViewById<ImageView>(R.id.glide_test).load(
            turnWebp(
                "https://oss-console-img-demo-cn-hangzhou.oss-cn-hangzhou.aliyuncs.com/example.jpg"
            )
        )


        //if (Build.VERSION.SDK_INT > Build.VERSION_CODES.S_V2) {
        //    requestAllFilePermission(this, {
        //
        //    })
        //}
        btn.setOnClickListener {
//            val toast = Toast.makeText(this@MainActivity, "提示的文字", Toast.LENGTH_SHORT)
//            toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0)
//            toast.show()


            //com.heytap.book/com.qq.reader.activity.MainActivity
            //val intent = Intent(Intent.ACTION_VIEW, Uri.parse("book://"))
            //intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
            //startActivity(intent)




            //startActivity(Intent(this, FlowTestActivity::class.java))
//            testImgAlpha()
//            showHideViewWidthAnim()
//            testDialog(it)
//            testGradient()
//            testShapeDrawable(it)
//            testText()
//            testVibrate()
//            testStep()
//            getParam()
//            startActivity(Intent(this, StepActivity::class.java))
//            testDouyin()
//            testDialogPosition()
//            testPoster()
//            testToast()
//            testSysShare()
//            Log.e("alarm", "view clicked...")

//            lottieView.drawable?.bounds?.toString()?.let { it1 -> Log.e("rect", it1) }

//            testFlutter()
//            testFlutterFragment()
//            startActivity(Intent(this, AnimTestActivity::class.java))
//            startActivity(Intent(this, ScrollerTestActivity::class.java))
//            startActivity(Intent(this, ViewPagerTestActivity::class.java))
//            startActivity(Intent(this, RecyclerTestActivity::class.java))
//            startActivity(Intent(this, MdnsTestActivity::class.java))
//            startActivity(Intent(this, TabTestActivity::class.java))
//            startActivity(Intent(this, SlideDeleteTestActivity::class.java))

//            DiscoverFloatShopFilterPop(this@MainActivity).show()

//            findViewById<ImageView>(R.id.test).setColorFilter(Color.GREEN)
//            testAnim()

//            findViewById<TextView>(R.id.click_view).text = Html.fromHtml("这个<font color='#ff0000'><big>大</big></font>字<font color='#0000ff'>颜色</font>很好看",
//                Html.FROM_HTML_MODE_LEGACY)

//            findViewById<TextView>(R.id.click_view).text = Html.fromHtml("<big>快 <b>8</b>/</big>14  <big>慢 <b>4</b>/</big>6",
//                Html.FROM_HTML_MODE_LEGACY)

//            callPhone()
//            Log.e("height", "btn height:" + btn.height)
//            Log.e("height", "50 height:" + dp2px(200f))
//            Log.e("height", "50 height:" + 200.dp)
//            showMask()

//            testLottie()

//            testRichText()

//            testValueAnimator()
//            testScreenInfo()

//            getBottomNavBarHeight()

//            startActivity(Intent(this, SnapHelperActivity::class.java))
//            startActivity(Intent(this, AnimIntercepterActivity::class.java))

//            testHwInstallInfo()

//            testLifecycleScope()
//            chooseFile()
//            QuitTeamDialog(this, "test") { }.show()
//            downloadFile()
//            startActivity(Intent(this, LottieAnimTestActivity::class.java))
//            Log.e("encod", "support hevc:${isH265DecoderSupport()}")
//            testTimeFormat()
//            testDotAnim()
//            testProfile()
//            Log.e("main", "test is $test")
//            testIconShowHide()
//            startActivity(Intent(this, SpanableTestActivity::class.java))

            //testRetrofit()

//            systemShare()
            //startActivity(Intent(this, CompassActivity::class.java))
            //permissionX()
//            startActivity(Intent(this, LeakTestActivity::class.java))


//            rxjavaStreamTest()
//            requestPermissions()
            chooseAfsFile()
        }

        findViewById<View>(R.id.img_cloud_left).setOnClickListener {
            testPopup(it)
        }
//        testLabels()
        testMyTab()
        testMyDots()

        initHomeTabBehavior()

        ImFileUtil.init(applicationContext)

        findViewById<TextView>(R.id.click_view)?.let {
            it.post {
                Log.e("line", "${it.getLayout().getEllipsisCount(1)}")
        }
        }


        val androidId: String = Settings.Secure.getString(contentResolver, Settings.Secure.ANDROID_ID)
        Log.d("Android", "Android ID : $androidId")




        findViewById<VideoView>(R.id.video_view)?.let{
            it.setVideoURI(Uri.parse("http://10.114.38.226:8090/files/zeekrvideo2od_vp9.webm"))
            it.start()

            it.setMediaController(MediaController(this));

        }


        Debug.startMethodTracing("test.trace")


    }

    override fun onDestroy() {
        super.onDestroy()
        Debug.stopMethodTracing()

    }


    //private val toastBinding: VehicleToastKeyPhoneCommonBinding by inflate()
    //private val customToast: Toast by lazy {
    //    Toast(this).apply {
    //        setGravity(Gravity.CENTER, 0, 0)
    //        duration = Toast.LENGTH_SHORT
    //        view = toastBinding.root
    //    }
    //}
    //fun testToast() {
    //
    //}

    val subject = PublishSubject.create<String>()

    fun rxjavaStreamTest() {
        subject.sample(30, TimeUnit.MILLISECONDS).observeOn(Schedulers.io())
            .subscribeOn(Schedulers.io())
            .subscribe(object : io.reactivex.Observer<String> {
                var disposable: Disposable? = null
                var times = 0
                override fun onSubscribe(d: Disposable) {
                    disposable = d
                }

                override fun onNext(bean: String) {
                    //if (bean.isArrowAnimator()) {
                    //    if (times == 3) {
                    //        mRpaBean.setArrowPhase(mRpaBean.getArrowPhase() - 2)
                    //        times = 0
                    //    } else {
                    //        times++
                    //    }
                    //}
                    //postInvalidate()
                    "onNext".logi("reactnative")
                }

                override fun onError(e: Throwable) {}
                override fun onComplete() {
                    disposable!!.dispose()
                }
            })

        subject.onNext("kkkkkk")
    }

    /**
     * 使用系统api分享文本/图片，参考链接：https://developer.android.google.cn/training/sharing?hl=zh-cn
     */
    fun systemShare(){
        systemShareText()
        //动态申请获取访问 读写磁盘的权限
//        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S_V2) {
//            if (ContextCompat.checkSelfPermission(this,
//                    Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
//
//                ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE), 101);
//            } else {
//                selectPicShare()
//            }
//        } else {
//            selectPicShare()
//        }
    }

    private fun systemShareText() {
        val shareIntent = Intent(Intent.ACTION_SEND)
        shareIntent.type = "text/plain"
        shareIntent.putExtra(Intent.EXTRA_TEXT, "https://item.jd.com/10101352914801.html")
        shareIntent.putExtra(Intent.EXTRA_SUBJECT, "Subject of the message")

        startActivity(Intent.createChooser(shareIntent, "Share link via"))
    }

    private fun systemShareFile(uri: Uri?) {
        val share = Intent.createChooser(Intent().apply {
            action = Intent.ACTION_SEND
            //type = "image/*"
            type = "*/*"
            putExtra(Intent.EXTRA_TEXT, "text。。。")

            // (Optional) Here you're setting the title of the content
            putExtra(Intent.EXTRA_TITLE, "Introducing content previews")

            // (Optional) Here you're passing a content URI to an image to be displayed
            //data = contentUri
            flags = Intent.FLAG_GRANT_READ_URI_PERMISSION

            putExtra(Intent.EXTRA_STREAM, uri)

        }, null)
        startActivity(share)
    }

    private val permissionInterceptor = object : OnPermissionsInterceptListener {
        override fun requestPermission(
            fragment: Fragment?,
            permissionArray: Array<out String>?,
            call: OnRequestPermissionListener?,
        ) {

        }

        override fun hasPermissions(
            fragment: Fragment?,
            permissionArray: Array<out String>?,
        ): Boolean {
            return permissionArray?.getOrNull(0) != Manifest.permission.CAMERA
        }

    }
    private fun selectPicShare() {
        PictureSelector.create(this)
            .openGallery(SelectMimeType.ofImage())
            //.setSelectorUIStyle(getWeChartSelectorStyle(context))
            .setLanguage(LanguageConfig.UNKNOWN_LANGUAGE)
            //.setImageEngine(GlideEngine.createGlideEngine())
            .setMaxSelectNum(1)
            .setMinSelectNum(1)// 最小选择数量
            .setImageSpanCount(3)// 每行显示个数
            .isEmptyResultReturn(false)// 未选择数据时点击按钮是否可以返回
            .setSelectionMode(SelectModeConfig.SINGLE)//多选还是单选
            .isPageStrategy(true)//分页模式
            .isOriginalControl(true)//是否开启原图功能
            .isDisplayCamera(true)//是否显示相机入口
            .isOpenClickSound(true)//是否开启点击声音
            .isFastSlidingSelect(true)//快速滑动选择
            .isPreviewFullScreenMode(true)//预览点击全屏效果
            .isPreviewZoomEffect(true)//预览缩放效果
            .isPreviewImage(true)
            .setImageEngine(GlideEngine.createGlideEngine())
            .isMaxSelectEnabledMask(true)//达到最大选择数是否开启禁选蒙层
            .isDirectReturnSingle(false)//单选时是否立即返回
            //            .setRecyclerAnimationMode(AnimationType.ALPHA_IN_ANIMATION)//相册列表动画效果
            //.setSelectedData(config.data)// 传入已选图片
            //.setCropEngine(if (config.isCrop) ImageFileCropEngine() else null)//设置相册裁剪引擎
            //.setCompressEngine(true)//设置相册压缩引擎
            //.isGif(showGif ?: false)
            .setPermissionsInterceptListener(permissionInterceptor)
            .forResult(object : OnResultCallbackListener<LocalMedia> {
                override fun onResult(result: ArrayList<LocalMedia>?) {
                    val share = Intent.createChooser(Intent().apply {
                        action = Intent.ACTION_SEND
                        type = "image/*"
                        putExtra(Intent.EXTRA_TEXT, "text。。。")

                        // (Optional) Here you're setting the title of the content
                        putExtra(Intent.EXTRA_TITLE, "Introducing content previews")

                        // (Optional) Here you're passing a content URI to an image to be displayed
                        //data = contentUri
                        flags = Intent.FLAG_GRANT_READ_URI_PERMISSION

                        putExtra(Intent.EXTRA_STREAM, Uri.parse(result?.get(0)?.path))

                    }, null)
                    startActivity(share)
                }

                override fun onCancel() {
                }
            })
    }

    fun bitmap2Bytes(bitmap: Bitmap): ByteArray {
        // 创建一个ByteArrayOutputStream对象
        val byteArrayOutputStream = ByteArrayOutputStream();

        // 将Bitmap压缩为JPEG格式的二进制数据，并写入ByteArrayOutputStream
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream);

        // 获取转换后的二进制数据流
        return byteArrayOutputStream.toByteArray();

        // 现在，bitmapData就是Bitmap的二进制数据流

    }

    /**
     * 参考链接：https://guolin.blog.csdn.net/article/details/127024559
     */
    fun permissionX(){
        PermissionX.init(this)
            .permissions(Manifest.permission.READ_CONTACTS, Manifest.permission.CAMERA, Manifest.permission.CALL_PHONE)
            .request { allGranted, grantedList, deniedList ->
                if (allGranted) {
                    Toast.makeText(this, "All permissions are granted", Toast.LENGTH_LONG).show()
                } else {
                    Toast.makeText(this, "These permissions are denied: $deniedList", Toast.LENGTH_LONG).show()
                }
            }
    }

    fun testHideAnim() {
        val view = findViewById<View>(R.id.test_view)
        if (view.marginBottom == -100.dp) {
            AnimUtil.animBottomMargin(view, 0, false, 300)
        } else {
            AnimUtil.animBottomMargin(view, -100.dp, false, 300)
        }
    }


    fun testRetrofit(){
//        https://divaid.github.io/resources/json/books.json
//        retrofitHelper.getRetrofit("https://divaid.github.io/").create(ITestInterface::class.java).testHttp().observe(this) {
//            Log.e("retrofit", it)
//        }

        //http://192.168.1.105:8080/testRetrofit
//        retrofitHelper.create(ITestInterface::class.java).testLocalHttp().observe(this) {
//            Log.e("retrofit", it.data?.name ?: "resutl ...")
//        }


        testInterface1.testRetrofit().request(this) {
            Log.e("retrofit", "testRetrofit:${JSON.toJSONString(it)}")
        }

        testInterface.getNewsList().request(this) {
            Log.e("retrofit", "getNewsList:${JSON.toJSONString(it)}")
        }
        methodTestInterface.test().request(this) {
            Log.e("retrofit", "test:${JSON.toJSONString(it)}")
        }

        methodTest1Interface.testArr().request(this) {
            Log.e("retrofit", "testArr:${JSON.toJSONString(it)}")
        }
    }


    private var iconView: FloatIconView? = null
    fun testIconShowHide() {
        if (iconView == null) {
            iconView = FloatIconView(findViewById(R.id.icon_parent), this)
            iconView?.checkShow(findViewById(R.id.behavior_list))
        }

//        findViewById<RecyclerView>(R.id.behavior_list).addOnScrollListener(object :
//            RecyclerView.OnScrollListener() {
//            override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
//                super.onScrollStateChanged(recyclerView, newState)
//                iconView?.removeCallbacks(showTask)
//                if (newState == RecyclerView.SCROLL_STATE_IDLE) {
//                    iconView?.postDelayed(showTask, 300)
//                } else {
//                    iconView?.hide()
//                }
//            }
//        })
//        iconView?.show()
    }

    var test = 0
    get() {
        if (field == 0) {
            testSetGet()
        }
        return field
    }
    private fun testSetGet() {
        test = 1
    }

    //profile中的arrange by app可查分配了哪些对象，arrange by callstack可查看由哪个方法分配的对象
    private fun testProfile() {
        for (index in 0 .. 1000) {
            val s = String(charArrayOf('a', 'b', 'c'))
        }
    }


    private fun testDotAnim() {
        for (index in 0 until dotList.childCount) {
            val view = dotList.getChildAt(index)
            if (view.left < resources.displayMetrics.widthPixels) {
                dotList.getChildAt(index).startAnimation(getDotAnim(400f + index * 300))
                Log.e("dot", "anim...")
            }
        }
    }

    private fun getDotAnim(startX: Float): TranslateAnimation {
        val anim = TranslateAnimation(startX, 0f, 0f, 0f)
        anim.duration = 500
        anim.interpolator = DecelerateInterpolator()
        return anim
    }

    var pop: AlbumCarChoosePop? = null
    private fun testPopup(view: View){
        if (pop == null) {
            pop = AlbumCarChoosePop(view, this)
        }
        if (pop?.isShowing != true) {
            pop?.showAsDropDown(view)
        }
    }



    private val clickListener: View.OnClickListener = object :View.OnClickListener{
        override fun onClick(v: View?) {
            val tempRv = v?.parent as RecyclerView
            val distance = v.left - (((v.parent as View).width shr 1) - (v.width shr 1))
            if (distance > 0) {
                if (!tempRv.canScrollHorizontally(1)) {
                    return
                }
            } else if (distance < 0) {
                if (!tempRv.canScrollHorizontally(-1)) {
                    return
                }
            }
            tempRv.smoothScrollBy(
                v.left - (((v.parent as View).width shr 1) - (v.width shr 1)),
                0
            )
        }
    }


    private lateinit var rv: RecyclerView
    private fun testMyTab(){
        rv = findViewById(R.id.my_tab)
        rv.layoutManager = LinearLayoutManager(this, RecyclerView.HORIZONTAL, false)
        rv.adapter = AlbumTabAdapter(rv)
    }

    class AlbumTabAdapter(var recyclerView: RecyclerView): RecyclerView.Adapter<AlbumTabHolder>() {
        private var valueAnim = ValueAnimator.ofFloat(0f, 1f)
        private val selectColor = Color.parseColor("#242b29")
        private val normalColor = Color.parseColor("#8E9496")
        private val rColorDis = 0x8E - 0x24
        private val gColorDis = 0x94 - 0x2b
        private val bColorDis = 0x96 - 0x29
        private val selectSize = 21f
        private val normalSize = 15f

        private val textRestWidth = dp2px(33f)

        private val tabBeans = ArrayList<MyTabBean>()

        private val measurePaint = Paint()
        init {
            measurePaint.textSize = 15f
            measurePaint.strokeWidth = 0.5f
            measurePaint.style = Paint.Style.FILL_AND_STROKE

            tabBeans.add(MyTabBean("外观", "1"))
            tabBeans.add(MyTabBean("内饰", "1"))
            tabBeans.add(MyTabBean("细节", "1"))
            tabBeans.add(MyTabBean("Lifestyle", "1"))
        }

        private var onClickListener = View.OnClickListener {
            val position = it.tag as Int
            if (position == lastSelectPosition) {
                return@OnClickListener
            }

            (it as TextView)

            moveToCenter(it)

            targetView = it

            setAnim()
            valueAnim.start()

            lastSelectPosition = it.tag as Int
        }

        private fun setAnim(){
            valueAnim = ValueAnimator.ofFloat(0f, 1f)
            valueAnim.duration = 200
            valueAnim.addUpdateListener {
                val progress = it.animatedValue as Float
                lastSelectView?.textSize = selectSize - (progress * 6)
                targetView?.textSize = normalSize + progress * 6


                val tr = (0x8E - progress * rColorDis).toInt()
                val tg = (0x94 - progress * gColorDis).toInt()
                val tb = (0x96 - progress * bColorDis).toInt()
                val tColor = ((0xFF shl 24) or (tr shl 16) or (tg shl 8) or tb)
                targetView?.setTextColor(tColor)

                targetView?.paint?.strokeWidth = progress + 0.4f

                val lr = (0x24 + progress * rColorDis).toInt()
                val lg = (0x2b + progress * gColorDis).toInt()
                val lb = (0x29 + progress * bColorDis).toInt()
                val lColor = ((0xFF shl 24) or (lr shl 16) or (lg shl 8) or lb)
                lastSelectView?.setTextColor(lColor)
                lastSelectView?.paint?.strokeWidth = (1 - progress) + 0.4f
            }

            valueAnim.doOnEnd {
                lastSelectView = targetView
                targetView = null
            }
        }

        private var lastSelectView: TextView? = null
        private var targetView: TextView? = null
        private var lastSelectPosition = 0
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AlbumTabHolder {
            val title = TextView(parent.context)
            title.layoutParams = ViewGroup.LayoutParams(150, ViewGroup.LayoutParams.MATCH_PARENT)
            title.gravity = Gravity.CENTER
            title.setOnClickListener(onClickListener)
            title.setTextColor(Color.parseColor("#8E9496"))
            title.paint?.style = Paint.Style.FILL_AND_STROKE
            return AlbumTabHolder(title)
        }

        override fun onBindViewHolder(holder: AlbumTabHolder, position: Int) {
            holder.item.textSize = normalSize
            holder.item.paint.strokeWidth = 0.4f
            holder.item.layoutParams.width = (holder.item.paint.measureText(tabBeans[position].name) + textRestWidth).toInt()

            if (lastSelectPosition == position) {
                holder.item.textSize = selectSize
                lastSelectView = holder.item
                holder.item.setTextColor(selectColor)
                holder.item.paint.strokeWidth = 1.4f
            } else {
                holder.item.setTextColor(normalColor)
            }
            holder.item.text = tabBeans[position].name
            holder.item.tag = position
        }

        override fun getItemCount(): Int {
            return tabBeans.size
        }

        private fun moveToCenter(item: View){
            val distance = item.left - (((item.parent as View).width shr 1) - (item.width shr 1))
            if (distance > 0) {
                if (!recyclerView.canScrollHorizontally(1)) {
                    return
                }
            } else if (distance < 0) {
                if (!recyclerView.canScrollHorizontally(-1)) {
                    return
                }
            }
            recyclerView.smoothScrollBy(
                item.left - (((item.parent as View).width shr 1) - (item.width shr 1)),
                0
            )
        }

        data class MyTabBean(var name: String, var id: String?)
    }

    class AlbumTabHolder(var item: TextView): RecyclerView.ViewHolder(item)


    private lateinit var dotList: RecyclerView
    private fun testMyDots(){
        dotList = findViewById(R.id.my_dots)
        dotList.layoutManager = LinearLayoutManager(this, RecyclerView.HORIZONTAL, false)
        dotList.adapter = AlbumDotAdapter(dotList)
        dotList.post {
            testDotAnim()
        }
    }

    class AlbumDotAdapter(var recyclerView: RecyclerView): RecyclerView.Adapter<AlbumDotHolder>() {
        private var valueAnim = ValueAnimator.ofFloat(0f, 1f)

        private var lastSelectView: FrameLayout? = null
        private var targetView: FrameLayout? = null
        private var lastSelectPosition = 0
        private val normalWidth = dp2px(33f)
        private val selectWidth = dp2px(36f)
        private val sizeMinus = selectWidth - normalWidth
        private var dotNormalParam = FrameLayout.LayoutParams(normalWidth, normalWidth)
        private var dotSelectParam = FrameLayout.LayoutParams(selectWidth, selectWidth)
        init {
            dotNormalParam.gravity = Gravity.CENTER
            dotSelectParam.gravity = Gravity.CENTER
        }

        private var onClickListener = View.OnClickListener {
            val position = it.tag as Int
            if (position == lastSelectPosition) {
                return@OnClickListener
            }

            moveToCenter(it)

            targetView = it as FrameLayout?

            setAnim()
            valueAnim.start()

            lastSelectPosition = it.tag as Int
        }

        private fun setAnim(){
            valueAnim = ValueAnimator.ofFloat(0f, 1f)
            valueAnim.duration = 200
            valueAnim.addUpdateListener {
                val progress = it.animatedValue as Float
                val toNormalParam = FrameLayout.LayoutParams((selectWidth - progress * sizeMinus).toInt(), (selectWidth - progress * sizeMinus).toInt())
                toNormalParam.gravity = Gravity.CENTER
                val toSelectParam = FrameLayout.LayoutParams((normalWidth + progress * sizeMinus).toInt(), (normalWidth + progress * sizeMinus).toInt())
                toSelectParam.gravity = Gravity.CENTER
                lastSelectView?.getChildAt(0)?.layoutParams = toNormalParam
                targetView?.getChildAt(0)?.layoutParams = toSelectParam

                lastSelectView?.getChildAt(0)?.background?.alpha = (255 * (1 - progress)).toInt()
                targetView?.getChildAt(0)?.background?.alpha = (255 * progress).toInt()
            }

            valueAnim.doOnEnd {
                lastSelectView = targetView
                targetView = null
            }
        }

        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AlbumDotHolder {
            val dotParent = FrameLayout(parent.context)
            dotParent.layoutParams = ViewGroup.MarginLayoutParams(dp2px(52f), dp2px(52f))

            val dot = ImageView(parent.context)
            dot.setPadding(dp2px(6f), dp2px(6f), dp2px(6f), dp2px(6f))
//            val drawable = GradientDrawable()
//            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
//                drawable.setColors(intArrayOf(Color.parseColor("#F2F3F5"), Color.WHITE), FloatArray(0))
//            }
//            drawable.shape = GradientDrawable.OVAL
//            drawable.gradientType = GradientDrawable.RADIAL_GRADIENT
//            drawable.alpha = 0
//            drawable.gradientRadius = 80f

            val drawable = parent.context.getDrawable(R.drawable.dot_bg) as GradientDrawable
//            drawable.gradientRadius = normalWidth.toFloat()
            dot.background = drawable

            val param = FrameLayout.LayoutParams(normalWidth, normalWidth)
            param.gravity = Gravity.CENTER
            dot.layoutParams = param


            dotParent.setOnClickListener(onClickListener)
            dotParent.addView(dot)
            return AlbumDotHolder(dotParent, dot)
        }

        override fun onBindViewHolder(holder: AlbumDotHolder, position: Int) {
            if (position % 2== 0) {
                holder.dot.setImageResource(R.mipmap.dot1)
            } else {
                holder.dot.setImageResource(R.mipmap.dot2)
            }

            if (lastSelectPosition == position) {
                lastSelectView = holder.parent
                holder.dot.layoutParams = dotSelectParam
                holder.dot.background.alpha = 255
            } else {
                holder.dot.layoutParams = dotNormalParam
                holder.dot.background.alpha = 0
            }
            holder.parent.tag = position
        }

        override fun getItemCount(): Int {
            return 20
        }

        private fun moveToCenter(item: View){
            val distance = item.left - (((item.parent as View).width shr 1) - (item.width shr 1))
            if (distance > 0) {
                if (!recyclerView.canScrollHorizontally(1)) {
                    return
                }
            } else if (distance < 0) {
                if (!recyclerView.canScrollHorizontally(-1)) {
                    return
                }
            }
            recyclerView.smoothScrollBy(
                item.left - (((item.parent as View).width shr 1) - (item.width shr 1)),
                0
            )
        }

    }

    class AlbumDotHolder(var parent: FrameLayout, var dot: ImageView): RecyclerView.ViewHolder(parent)

    private fun testTimeFormat(){
        var todayCalendar = Calendar.getInstance()
        var durationCalendar = Calendar.getInstance()
        durationCalendar.timeInMillis = 1653235199000

        val todayDayMill = todayCalendar.timeInMillis - todayCalendar.get(Calendar.HOUR_OF_DAY) * 3600000 - todayCalendar.get(Calendar.MINUTE) * 60000 - todayCalendar.get(Calendar.SECOND) * 1000 - todayCalendar.get(Calendar.MILLISECOND)
        val durationDayMill = durationCalendar.timeInMillis - durationCalendar.get(Calendar.HOUR_OF_DAY) * 3600000 - durationCalendar.get(Calendar.MINUTE) * 60000 - durationCalendar.get(Calendar.SECOND) * 1000 - durationCalendar.get(Calendar.MILLISECOND)
        val result = todayDayMill - durationDayMill
        Log.e("time", "result:${result}")
        when {
            result < 86400000 -> {//一天之内
                Log.e("time", "一天之内")
            }
            result < 172800000 -> {//昨天
                Log.e("time", "昨天")
            }
            result < 259200000 -> {//前天
                Log.e("time", "前天")
            }
            result < 345600000 -> {//四天之内
                Log.e("time", "四天内")
            }
            result < 432000000 -> {//五天之内
                Log.e("time", "五天之内")
            }

            result < 518400000 -> {//六天之内
                Log.e("time", "六天之内")
            }

            result < 604800000 -> {//七天之内
                Log.e("time", "七天之内")
            }
//            result < 2.592E9 -> {//三十天之内
//                Log.e("time", "三十天之内")
//            }
//            result < 3.1536E10 -> {//三百六十五天之内
//                Log.e("time", "三百六十五天之内")
//            }
//            else -> {//一年之外
//                Log.e("time", "一年之外")
//            }
            todayCalendar.get(Calendar.YEAR) == durationCalendar.get(Calendar.YEAR) -> {//同一年
                Log.e("time", "同一年")
            }
            else -> {//不同年
                Log.e("time", "不同年")
//                "${targetCalendar.get(Calendar.YEAR)}年${targetCalendar.get(Calendar.MONTH) + 1}月${targetCalendar.get(Calendar.DAY_OF_MONTH)}日"
            }
        }
    }

    /**
     * 检测是否支持H265硬解码
     * @return 检测结果
     */
    public fun isH265DecoderSupport():Boolean{
        val count = MediaCodecList.getCodecCount();
        for(i in 0..count){
            val info = MediaCodecList.getCodecInfoAt(i);
            val name = info.getName();
            if(name.contains("decoder") && name.contains("hevc")){
                return true;
            }
        }
        return false;
    }


    private val chooseFileContracts = registerForActivityResult(ActivityResultContracts.GetContent()){
        systemShareFile(it)
        it?.let { it1 ->
            ImFileUtil.copyFileToCache(applicationContext, it1, object : OnFileCopiedListener {
                override fun onFileCopy(name: String, path: String) {
                    Log.e("main", "name: $name path: $path")
                }

                override fun onCopyFailed(path: String, msg: String) {
                    Log.e("main", "path: $path msg: $msg")
                }
            })
        }
    }
    private fun chooseFile(){
        chooseFileContracts.launch("*/*")
    }

    var handler = object :Handler(Looper.myLooper()!!){
        override fun handleMessage(msg: Message) {
            super.handleMessage(msg)
            Log.e("main", "running...")
            sendEmptyMessageDelayed(0, 1000)
        }
    }
    private fun testLifecycleScope(){
        lifecycleScope.launchWhenResumed {
//            handler.sendEmptyMessageDelayed(0, 1000)

//            flow<Int>{
////                emit(0)
////                Thread.sleep(1000)
////                emit(0)
////                Thread.sleep(1000)
////                emit(0)
////                Thread.sleep(1000)
////                emit(0)
////                Thread.sleep(1000)
////                emit(0)
////                Thread.sleep(1000)
////                Thread.sleep(5000)
//                TestUtil.test()
//                emit(0)
//            }.flowOn(Dispatchers.IO).collect {
//                Log.e("main", "running...")
//            }

            TestUtil.test().collect { result ->
                Log.e("main", "result is $result")
                test()
            }
        }
    }

    private fun downloadFile(){
        CoroutineScope(Dispatchers.IO).launch {
            val file = File(cacheDir, "data.json")
            if (!file.exists()) {
                file.createNewFile()
            }
            try {
                Log.e("time", "start time :${System.currentTimeMillis()}")
                val url= URL("https://www.baidu.com/native-cache/data.json.zip")
                val connect=url.openConnection()
                val input=connect.getInputStream()
                val br = BufferedReader(InputStreamReader(input));
                var line:String?

                val writer = BufferedWriter(FileWriter(file))

//                val sb = StringBuffer()
                line = br.readLine()
                while (line != null) {
//                    sb.append(line)
                    writer.write(line)
                    line = br.readLine()
                }
                writer.close()

                Log.e("time", "end time :${System.currentTimeMillis()}")
//                Log.e("down", sb.toString())
//            return sb.toString()
            } catch ( e:Exception) {
                e.printStackTrace()
            }
        }
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
    }

    //获取华为手机应用安装信息（是否从广告处下载等信息）：https://developer.huawei.com/consumer/cn/doc/distribution/promotion/bp-functions-intelligent-subcontract-attribution-0000001285288280
    private fun testHwInstallInfo(){
        HwInstallInfoUtil.getTrackId(this, "com.david.func_test")
    }

    inner class MyHolder(itemView:View): RecyclerView.ViewHolder(itemView)

    private lateinit var homeTabBehavior: BottomSheetBehavior<View>

    private var isClickChange = false

    private fun initHomeTabBehavior(){
        findViewById<View>(R.id.nav_top).setOnClickListener {
            Log.e("state", "click ${homeTabBehavior.state}")
            isClickChange = true
            if (homeTabBehavior.state == BottomSheetBehavior.STATE_COLLAPSED) {
                homeTabBehavior.isHideable = false
                homeTabBehavior.state = BottomSheetBehavior.STATE_HALF_EXPANDED
            } else {
                homeTabBehavior.isHideable = true
                homeTabBehavior.state = BottomSheetBehavior.STATE_COLLAPSED
            }
        }
        val recycler = findViewById<RecyclerView>(R.id.behavior_list)
        recycler.layoutManager = LinearLayoutManager(this)
        recycler.adapter = object: RecyclerView.Adapter<MyHolder>() {
            override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyHolder {
                if (viewType == 0) {
                    val title = TextView(parent.context)
                    title.text = "hahah"
                    title.setPadding(0, 30, 0 ,30)
                    return MyHolder(title)
                } else {
                    return MyHolder(LayoutInflater.from(parent.context).inflate(R.layout.item_pagerviewgroup, parent, false))
                }
            }

            override fun onBindViewHolder(holder: MyHolder, position: Int) {

            }

            override fun getItemCount(): Int {
                return 150
            }

            override fun getItemViewType(position: Int): Int {
                return if (position % 5 == 0) {
                    1
                } else {
                    0
                }
            }

        }

        val view = findViewById<View>(R.id.bottom_tab_sheet)
        homeTabBehavior = BottomSheetBehavior.from(view)
        homeTabBehavior.state = BottomSheetBehavior.STATE_HALF_EXPANDED
        homeTabBehavior.addBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() {
            private var lastSlide = 0f
            private var lastState = BottomSheetBehavior.STATE_HALF_EXPANDED
            private var curHeight = 0
            override fun onStateChanged(bottomSheet: View, newState: Int) {
//                if (newState == BottomSheetBehavior.STATE_COLLAPSED) {
//                    binding.mapView.cardCallHide()
//                }


                if (STATE_SETTLING == newState) {
                    if (isClickChange) {
                        return
                    }

                    if ((lastState == BottomSheetBehavior.STATE_COLLAPSED )
                    ) {
                        if (lastSlide > 0.1) {
                            homeTabBehavior.state = BottomSheetBehavior.STATE_HALF_EXPANDED
                            lastState = BottomSheetBehavior.STATE_HALF_EXPANDED
                        } else {
                            homeTabBehavior.state = BottomSheetBehavior.STATE_COLLAPSED
                            lastState = BottomSheetBehavior.STATE_COLLAPSED
                        }
                    } else if (lastState == BottomSheetBehavior.STATE_HALF_EXPANDED) {
                        if (lastSlide > 0.55) {
                            homeTabBehavior.state = BottomSheetBehavior.STATE_EXPANDED
                            lastState = BottomSheetBehavior.STATE_EXPANDED
                        } else if (lastSlide < 0.45) {
                            homeTabBehavior.state = BottomSheetBehavior.STATE_COLLAPSED
                            lastState = BottomSheetBehavior.STATE_COLLAPSED
                        }
                    } else if (lastState == BottomSheetBehavior.STATE_EXPANDED) {
                        if (lastSlide < 0.9) {
                            homeTabBehavior.state = BottomSheetBehavior.STATE_HALF_EXPANDED
                            lastState = BottomSheetBehavior.STATE_HALF_EXPANDED
                        } else {
                            homeTabBehavior.state = BottomSheetBehavior.STATE_EXPANDED
                            lastState = BottomSheetBehavior.STATE_EXPANDED
                        }
                    }
                }
                if (newState == STATE_IDLE) {
                    isClickChange = false
                }
                Log.e("state", "newState is $newState")
            }

            override fun onSlide(bottomSheet: View, slideOffset: Float) {
                lastSlide = slideOffset
                Log.e("slide", "$slideOffset")
                //处理右下角按钮偏移量
                if (slideOffset > 0f) {
//                    var behaviorShowHeight = if (lastSlide - slideOffset > 0) {
//                        bottomSheet.height - bottomSheet.height * (1 - slideOffset)
//                    } else {
//                        bottomSheet.height * slideOffset
//                    }.toInt()
//                    if (mViewModel.bizType == TabItemEnum.TAB0.tabType) {
//                        val minHeight = floatHomeWidget?.topMargin.ifInt() + floatHomeWidget?.maxHeight.ifInt() - floatHomeWidget?.param?.topMargin.ifInt()
//                        if (behaviorShowHeight < minHeight) {
//                            behaviorShowHeight = minHeight
//                        }
//                    } else {
//                        val minHeight = floatWidget?.topMargin.ifInt() + floatWidget?.maxHeight.ifInt() - floatWidget?.param?.topMargin.ifInt()
//                        if (behaviorShowHeight < minHeight) {
//                            behaviorShowHeight = minHeight
//                        }
//                    }
//                    binding.includeNav.navBtnLayout.updateLayoutParams<ViewGroup.MarginLayoutParams> { bottomMargin =
//                        (slideOffset * bottomSheet.height).toInt()
//                    }
//                    binding.mapView.updateLayoutParams<ViewGroup.MarginLayoutParams> { bottomMargin =
//                        (slideOffset * bottomSheet.height).toInt()
//                    }
//                    curHeight = behaviorShowHeight
//                    lastSlide = slideOffset
                }
            }
        })
    }

    private fun getBottomNavBarHeight(){

            var result = 0
            if (hasNavBar()) {
                var res = getResources();
                var resourceId = res.getIdentifier("navigation_bar_height", "dimen", "android");
                if (resourceId > 0) {
                    result = res.getDimensionPixelSize(resourceId);
                }
            }
        Log.e("result", result.toString())
            result;

    }

    /**
     * 检查是否存在虚拟按键栏
     */
    @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
    private fun  hasNavBar(): Boolean {
        var res = getResources()
        var resourceId = res.getIdentifier("config_showNavigationBar", "bool", "android");
        if (resourceId != 0) {
            var hasNav = res.getBoolean(resourceId);
            var sNavBarOverride = getNavBarOverride();
            if ("1".equals(sNavBarOverride)) {
                hasNav = false;
            } else if ("0".equals(sNavBarOverride)) {
                hasNav = true;
            }
            return hasNav;
        } else {
            return !ViewConfiguration.get(this).hasPermanentMenuKey();
        }
    }

    /**
     * 判断虚拟按键栏是否重写
     */
    private fun  getNavBarOverride():String? {
        var sNavBarOverride: String? = null
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            try {
                var c = Class.forName("android.os.SystemProperties");
                var m = c.getDeclaredMethod("get", String::class.java)
                m.setAccessible(true);
                sNavBarOverride = m.invoke(null, "qemu.hw.mainkeys") as String
            } catch ( e:Exception) {
            }
        }
        return sNavBarOverride;
    }

    //参考：https://blog.csdn.net/lu202032/article/details/119796731
    private fun testScreenInfo(){
        Log.e("screen", resources.displayMetrics.widthPixels.toString())
        Log.e("screen", resources.displayMetrics.heightPixels.toString())
        Log.e("screen", resources.displayMetrics.xdpi.toString())
        Log.e("screen", resources.displayMetrics.ydpi.toString())
        Log.e("screen", resources.displayMetrics.density.toString())
        Log.e("screen", resources.displayMetrics.densityDpi.toString())
        Log.e("screen", resources.displayMetrics.scaledDensity.toString())

        var height = 0;
        var resourceId = getApplicationContext().getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            height = getApplicationContext().getResources().getDimensionPixelSize(resourceId);
        }
        Log.e("screen", height.toString())
    }

    private fun testObjectAnimator(){
        animView = findViewById(R.id.view_showhide_anim_parent)
        val objectAnimator = ObjectAnimator.ofFloat(animView, View.TRANSLATION_X, 0f, 50f)
        objectAnimator.duration = 500
        objectAnimator.start()
    }

    //参考链接：https://cloud.tencent.com/developer/article/1963836  https://developer.android.google.cn/guide/topics/graphics/prop-animation?hl=zh-cn
    //根据进度设置view样式，如宽高，左右边距，颜色(ofArgb(0xffffffff,0xffff0000,0xff0000ff))等
    //valueAnimator修改值，在回调中修改view属性达到动画效果；ObjectAnimator直接修改某一属性(ofInt中传属性：如 View.TRANSLATION_Y)
    //插值器参考：https://blog.csdn.net/pzm1993/article/details/77926373
    private fun testValueAnimator(){
        animView = findViewById(R.id.view_showhide_anim_parent)
        val valueAnimator = ValueAnimator.ofInt(0, 100)
        valueAnimator.duration = 1000
        valueAnimator.interpolator = BounceInterpolator()
        valueAnimator.addUpdateListener { animator -> // 获得每次变化后的属性值
            val currentValue = animator.animatedValue as Int

            animView?.updateLayoutParams<ViewGroup.MarginLayoutParams> { bottomMargin = currentValue }
//            (animView?.layoutParams as ViewGroup.MarginLayoutParams).updateMargins(
//                bottom = currentValue
//            )
            // 每次值变化时，将值手动赋值给对象的属性
            // 即将每次变化后的值赋给按钮的宽度，这样就实现了按钮宽度属性的动态变化
//                view.getLayoutParams().width = currentValue


            // 步骤4：刷新视图，即重新绘制，从而实现动画效果
//                view.requestLayout()
        }
//        if (endVisibleGone) {
//            valueAnimator.doOnEnd {
//                view.visibility = View.GONE
//            }
//        }
        valueAnimator.start()
    }

    private fun testRichText(){
        btn.text = Html.fromHtml("<font style='border:1px solid' color='#ff0000'><b>99</b></font>", Html.FROM_HTML_MODE_LEGACY)
    }

    private fun testImgAlpha(){
        findViewById<ImageView>(R.id.img_cloud_left).alpha = 0.5f
    }

    var animParent:FrameLayout? = null
    var animView:View? = null
    var mTransitioner = LayoutTransition()

    //使用android:animateLayoutChanges设置view显示/隐藏时的动画(默认为透明度动画),参考连接：https://blog.csdn.net/harvic880925/article/details/50985596
    private fun showHideViewWidthAnim(){
        if (animParent == null) {
            animView = findViewById(R.id.view_showhide_anim_view)

            animParent = findViewById(R.id.view_showhide_anim_parent)
            //入场动画:view在这个容器中消失时触发的动画
            val animIn = ObjectAnimator.ofFloat(null, View.TRANSLATION_Y, 360f, 0f);
            mTransitioner.setAnimator(LayoutTransition.APPEARING, animIn)

            //出场动画:view显示时的动画
            val animOut = ObjectAnimator.ofFloat(null, View.TRANSLATION_Y, 0f, 360f);
            mTransitioner.setAnimator(LayoutTransition.DISAPPEARING, animOut)

            mTransitioner.setDuration(500)

            animParent?.layoutTransition = mTransitioner
        }

//        if (animView.visibility == View.VISIBLE) {
            animView?.isVisible = !animView?.isVisible!!
//        }

    }

    fun showMask(){
        val view = LayoutInflater.from(this).inflate(R.layout.layout_mask, findViewById(android.R.id.content), true)

    }

    fun callPhone(){
        val dialIntent = Intent(Intent.ACTION_DIAL, Uri.parse("tel:10086")) //直接拨打电话
        dialIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        application.startActivity(dialIntent)
    }

    private fun testAnim(){
        val rightAnim = AnimationUtils.loadAnimation(this, R.anim.anim_cloud_right)
        rightAnim.setAnimationListener(object :Animation.AnimationListener{
            override fun onAnimationStart(animation: Animation?) {}

            override fun onAnimationEnd(animation: Animation?) {
                val right = findViewById<View>(R.id.img_cloud_right)
                val left = findViewById<View>(R.id.img_cloud_left)
                val bg = findViewById<View>(R.id.img_cloud_bg)
                left.visibility = View.GONE
                right.visibility = View.GONE
                bg.visibility = View.GONE
            }

            override fun onAnimationRepeat(animation: Animation?) {}

        })
        findViewById<ImageView>(R.id.img_cloud_right).startAnimation(rightAnim)
        findViewById<ImageView>(R.id.img_cloud_left).startAnimation(AnimationUtils.loadAnimation(this, R.anim.anim_cloud_left))
        findViewById<View>(R.id.img_cloud_bg).startAnimation(AnimationUtils.loadAnimation(this, R.anim.anim_cloud_fade_bg))
    }

    var count = 0
    private fun testToast(){
        ToastUtils.instance.toast("hahahhaha${++count}")
    }

    var lottieView:LottieAnimationView? = null
    private fun testLottie(){
        if (lottieView == null) {
            lottieView = findViewById<LottieAnimationView>(R.id.lottie_view)
//        http://10.114.38.226:8090/files/boxmotion.zi

            //        lottieView.scaleY = resources.displayMetrics.density
//        lottieView.scaleX = resources.displayMetrics.density

//        lottieView.setAnimationFromUrl("http://10.114.38.226:8090/files/boxmotion.zip")
//        lottieView.setAnimationFromUrl("http://10.114.38.226:8090/files/boxmotion.json")
//        lottieView.maintainOriginalImageBounds = true
//        lottieView.clipToCompositionBounds = true
//        lottieView.composition?.bounds?.set(0,0,10,10)

            lottieView?.setAnimation("data.json")

//        lottieView.repeatMode =  LottieDrawable.REVERSE
//        lottieView.repeatCount =  LottieDrawable.INFINITE
            lottieView?.repeatMode =  LottieDrawable.RESTART
            lottieView?.repeatCount =  1
            lottieView?.addAnimatorListener(object : Animator.AnimatorListener {
                override fun onAnimationStart(animation: Animator) {

                }

                override fun onAnimationEnd(animation: Animator) {
                    Log.e("lottie", "onAnimationEnd...")
                }

                override fun onAnimationCancel(animation: Animator) {
                }

                override fun onAnimationRepeat(animation: Animator) {
                }
            })
//        lottieView.setAnimationFromUrl("https://assets6.lottiefiles.com/packages/lf20_Tprkoc.json")
        }

        lottieView?.playAnimation()
    }

    private fun testPoster(){
        val bgBitmap = BitmapFactory.decodeResource(resources, R.drawable.share_bg_new)
        val qrBitmap = BitmapFactory.decodeResource(resources, R.drawable.qr_img)
        val avatar = BitmapFactory.decodeResource(resources, R.drawable.img_avatar)
        val avatarLabel = BitmapFactory.decodeResource(resources, R.drawable.role_label)
        val label = BitmapFactory.decodeResource(resources, R.drawable.poster_label)
        val nick = "昵称一二三四五六七八九十"

//        val builder = PosterCreator.Builder()
//            .setDesignWidth(1500)
//            .setDesignHeight(3248)
//            .addLastPaintRect(Color.parseColor("#FF5800"), Paint.Style.FILL, 0f, RectF(125f, 2976f, 136f, 3110f))
//            .addImage(bgBitmap, Rect(0, 0, bgBitmap.width, bgBitmap.height), Rect(0, 0, 1500, 3248))
//            .addImage(qrBitmap, Rect(0, 0, qrBitmap.width, qrBitmap.height), Rect(1085,2832,  1373, 3120))
//            .addTextBean(Color.parseColor("#24292B"), dp2px(18f), Paint.Style.FILL, nick, 126f, false, 2920f, true)
//            .addTextBean(Color.parseColor("#24292B"), dp2px(14f), Paint.Style.FILL, "长按识别二维码", 179f, false, 3020f)
//            .addTextBean(Color.parseColor("#24292B"), dp2px(14f), Paint.Style.FILL, "解锁你的极氪生活", 179f, false, 3100f)
//
//        builder.getPaint().textSize = dp2px(18f)
//        val width = builder.getPaint().measureText(nick)
//        builder.addImage(label, Rect(0, 0, label.width, label.height), Rect((width + 139).toInt(), 2880,
//            (width + 271).toInt(), 2922))
//
//        val bitmap = builder.create()

        val builder = PosterCreator.Builder()
            .setDesignWidth(1125)
            .setDesignHeight(2436)
            .addImage(bgBitmap, Rect(0, 0, bgBitmap.width, bgBitmap.height), Rect(0, 0, 1125, 2028))//背景图放上面
            .addRect(Color.WHITE, Paint.Style.FILL, 0f, RectF(0f, 2027f, 1125f, 2436f))
            .addImage(qrBitmap, Rect(0, 0, qrBitmap.width, qrBitmap.height), Rect(813,2125,  1029, 2341))
            .addImage(avatar, Rect(0, 0, avatar.width, avatar.height), Rect(96,2125,168,2197))
            .addImage(avatarLabel, Rect(0, 0, avatarLabel.width, avatarLabel.height), Rect(148,2177,168,2197))
            .addTextBean(Color.parseColor("#24292B"), dp2px(14f), Paint.Style.FILL, nick, 186f, false, 2175f, true)
            .addLastPaintRect(Color.parseColor("#FF5800"), Paint.Style.FILL, 0f, RectF(99f, 2235f, 107.7f, 2333f))
            .addTextBean(Color.parseColor("#24292B"), dp2px(12f), Paint.Style.FILL, "长按识别二维码", 130f, false, 2266.5f)
            .addTextBean(Color.parseColor("#24292B"), dp2px(12f), Paint.Style.FILL, "解锁你的极氪生活", 130f, false, 2322f)

        builder.getPaint().textSize = dp2px(14f)
        val width = builder.getPaint().measureText(nick)
        builder.addImage(label, Rect(0, 0, label.width, label.height), Rect((width + 206).toInt(), 2138,
            (width + 338).toInt(), 2180))

        val bitmap = builder.create()

        findViewById<ImageView>(R.id.test_image3).setImageBitmap(bitmap)
    }
    fun dp2px(dp: Float): Float {
        val r = Resources.getSystem()
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, r.displayMetrics)
    }

    private fun testDialogPosition(){
        val dialog = CustomDialog(this)

//        val params = dialog.window?.attributes
//        params?.width = WindowManager.LayoutParams.MATCH_PARENT
//        dialog.window?.attributes = params
//        dialog.window?.setGravity(Gravity.BOTTOM)

        dialog.show()
    }



    private fun testStep(){
        var cursor: Cursor? = null;
        try {
            cursor = getContentResolver()
                .query(Uri.parse("content://" + "com.miui.providers.steps" + "/item"), null, "_end_time between 1659924000000 and 1660010400000", null, null);

            val steps = LinkedList<Step>()

            if (cursor?.moveToFirst() == true) {
                do {
                    //_end_time between 1659974000 and 1660006800
                    var s = Step(cursor.getInt(0), cursor.getLong(1), cursor.getLong(2),
                        cursor.getInt(3),
                        cursor.getInt(4))
                    steps.add(s)
                } while (cursor.moveToNext())

                Log.e("step","count:"+ steps.size)
            }
        } catch ( e:Exception) {
            e.printStackTrace()
//            LogX.e(TAG, SUB_TAG, getName() + "; " + e.toString());
        }

        Log.e("step", "support:" + getBoolean("support_steps_provider", false))
    }

    fun getBoolean(name: String?, defaultValue: Boolean): Boolean {
        try {
            val featureParserClass = Class.forName("miui.util.FeatureParser")
            val method = featureParserClass.getMethod(
                "getBoolean",
                String::class.java,
                Boolean::class.javaPrimitiveType
            )
            return method.invoke(null, name, defaultValue) as Boolean
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return defaultValue
    }

    private fun testVibrate(){
//        val time = 100
//        VibrateUtils.vibrateOnce(this, time.toLong())
        VibrateUtils.startVibrate(this, longArrayOf(0, 25, 50, 10))
    }

    //宽度大于控件自动省略TextView
    private fun testText(){
        findViewById<LimitLengthTextView>(R.id.limit_text).setText("你哈哈哈你哈哈啦", "美食")
    }

    private fun testShapeDrawable(view: View) {
        val gd = GradientDrawable()
        gd.setColor(Color.parseColor("#0000ff"));
        gd.setCornerRadius(8f);
        gd.setStroke(2, Color.parseColor("#ff0000"));//描边的颜色和宽度
        view.background = gd

//        gd.setGradientType(GradientDrawable.RECTANGLE);

    }

    private fun testGradient(){
        val drawable = GradientDrawable().apply {
            shape = GradientDrawable.RECTANGLE
            colors = intArrayOf(
                Color.WHITE,
                Color.parseColor("#ffffffff"),
                Color.parseColor("#f1ffffff")
//                Color.parseColor("#e5ffffff")
            )
//            setGradientCenter(0.42f, 0f)
            orientation = GradientDrawable.Orientation.TOP_BOTTOM
        }
        findViewById<ImageView>(R.id.test_image3).setImageDrawable(drawable)
    }

    private fun testDialog(v:View){
        TestDialog(this).showViewBottom(v)
    }

    private fun testWorker(){
        val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager

        val intent = Intent(applicationContext, MainActivity::class.java)
            intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
        val pendingIntent:PendingIntent = PendingIntent.getBroadcast(applicationContext, 0, intent, FLAG_IMMUTABLE)
//        alarmManager.set(AlarmManager.RTC,System.currentTimeMillis() + 1000*20,"FLAG_IMMUTABLE",object :
//            AlarmManager.OnAlarmListener {
//            override fun onAlarm() {
//                Log.e("alarm", "OnAlarmListener.....")
//            }
//
//        }, Handler(
//            Looper.getMainLooper()));

        alarmManager.setAndAllowWhileIdle(AlarmManager.RTC, System.currentTimeMillis() + 1000*20,pendingIntent)




        val currentDate = Calendar.getInstance()
        val dueDate = Calendar.getInstance()

// 设置在大约 05:00:00 AM 执行
        dueDate.set(Calendar.HOUR_OF_DAY, 15)
        dueDate.set(Calendar.MINUTE, 17)
        dueDate.set(Calendar.SECOND, 0)

        if (dueDate.before(currentDate)) {
            dueDate.add(Calendar.HOUR_OF_DAY, 24)
        }

        val timeDiff = dueDate.timeInMillis - currentDate.timeInMillis
        val dailyWorkRequest = OneTimeWorkRequestBuilder<DailyWorker>()
            .setConstraints(Constraints.Builder().build()) .setInitialDelay(timeDiff, TimeUnit.MILLISECONDS)
            .addTag("TAG_OUTPUT").build()

        WorkManager.getInstance(this).enqueue(dailyWorkRequest)
    }

    private fun testLabels(){
        val labelsView: LabelsView = findViewById(R.id.label_view)
        val bean = TestBean("h啊哈哈")
        bean.strokeWidth = 2f
        bean.strokeColor = Color.YELLOW
        bean.bgColor = Color.BLACK
        labelsView.addLabels(arrayListOf(
            bean
            , TestBean( "h啊哈哈")
            , TestBean("t测测")
            , LabelBean("他他他")
            , LabelBean("了了")
            , LabelBean("和")
        )
        )
    }
}
val Int.dp get() = this.toFloat().dp.toInt()
val Float.dp
    get() = TypedValue.applyDimension(
        TypedValue.COMPLEX_UNIT_DIP,
        this,
        Resources.getSystem().displayMetrics
    )
class TestBean(text: String? = null): LabelBean(text){
    var labelId: String = ""
}

class Step {
    constructor(id: Int, mBeginTime: Long, mEndTime: Long, mMode: Int, mSteps: Int) {
        this.id = id
        this.mBeginTime = mBeginTime
        this.mEndTime = mEndTime
        this.mMode = mMode
        this.mSteps = mSteps
    }

    var id = 0
     var mBeginTime: Long = 0
     var mEndTime: Long = 0
     var mMode = 0
     var mSteps = 0
}

fun MainActivity.test(){
    Log.e("main", "main test...")
    AlertDialog.Builder(this).setTitle("test").show()
}